package com.nervenets.web.redis;

import com.google.gson.Gson;
import com.nervenets.utils.StringUtils;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * Created by Joe on 2017/12/16.
 */
@Component
public class RedisDao {
    private static final String EXECUTE_RESULT_OK = "OK";
    @Resource
    private RedisTemplate redisTemplate;

    private static String toJson(RedisDomain domain) {
        return new Gson().toJson(domain);
    }

    public boolean addString(String key, String value, int expire) {
        return (boolean) redisTemplate.execute((RedisCallback) rc -> {
            final Boolean result = rc.set(key.getBytes(), value.getBytes());
            if (result && expire > 0) {
                rc.expire(key.getBytes(), expire);
            }
            return result;
        });
    }

    public boolean setNx(String key, String value) {
        return (boolean) redisTemplate.execute((RedisCallback) rc -> rc.setNX(key.getBytes(), value.getBytes()));
    }

    public boolean addString(String key, String value) {
        return (boolean) redisTemplate.execute((RedisCallback) rc -> rc.set(key.getBytes(), value.getBytes()));
    }

    public boolean exist(String key) {
        return (boolean) redisTemplate.execute((RedisCallback) rc -> rc.exists(key.getBytes()));
    }

    public void delete(String key) {
        redisTemplate.execute((RedisCallback) rc -> rc.del(key.getBytes()));
    }

    public String getString(String key) {
        try {
            final byte[] result = (byte[]) redisTemplate.execute((RedisCallback) rc -> rc.get(key.getBytes()));
            return new String(result);
        } catch (Exception e) {
            return null;
        }
    }

    public long getExpired(String key) {
        return (long) redisTemplate.execute((RedisCallback) rc -> rc.ttl(key.getBytes()));
    }

    public void setExpired(String key, int expire) {
        redisTemplate.execute((RedisCallback) rc -> {
            return rc.expire(key.getBytes(), expire);
        });
    }

    public void delete(RedisDomain domain) {
        delete(domain.getRedisKey());
    }

    public boolean saveOrUpdate(RedisDomain domain) {
        return saveOrUpdate(domain, domain.getExpire());
    }

    public boolean saveOrUpdate(RedisDomain domain, int expire) {
        return addString(domain.getRedisKey(), toJson(domain), expire);
    }

    public <T extends RedisDomain> T getRedisDomain(String key, Class<? extends T> domainClass) {
        String jsonString = getString(key);
        if (!StringUtils.isEmpty(jsonString)) {
            return new Gson().fromJson(jsonString, domainClass);
        }
        return null;
    }

    public long incrBy(String key, long offset) {
        return (long) redisTemplate.execute((RedisCallback) rc -> {
            return rc.incrBy(key.getBytes(), offset);
        });
    }

    public long incr(String key) {
        return (long) redisTemplate.execute((RedisCallback) rc -> {
            return rc.incr(key.getBytes());
        });
    }
}
